#ifndef __nxrouting_h__
#define __nxrouting_h__

#include "nxrouting_pkt.h"
#include "nxrouting_rtable.h"
#include <agent.h>
#include <packet.h>
#include <trace.h>
#include <priqueue.h>
#include <timer-handler.h>
#include <random.h>
#include <classifier-port.h>
#include <mobilenode.h>
#include "arp.h"
#include "ll.h"
#include "mac.h"
#include "ip.h"
#include "delay.h"

#define TIME_FORMAT "%.15g"
#define CURRENT_TIME Scheduler::instance().clock()
#define JITTER (Random::uniform()*0.5)

//add by tl to support multi-interface
#define MAX_IF  128
//end add by tl

class NXrouting; // forward declaration

/* Timers */

class NXrouting_PktTimer : public TimerHandler {
    public:
    NXrouting_PktTimer(NXrouting* agent) : TimerHandler() {
    	agent_ = agent;
    }

    protected:
    NXrouting* agent_;
    virtual void expire(Event* e);
};

/* Agent */

class NXrouting : public Agent {

   /* Friends */
   friend class NXrouting_PktTimer;

   /* Private members */
   nsaddr_t ra_addr_;
   //nxrouting_state state_;
   nxrouting_rtable rtable_;
   int accessible_var_;
   u_int8_t seq_num_;

   protected:

   MobileNode* node_;
   PortClassifier* dmux_; // For passing packets up to agents.
   Trace* logtarget_; // For logging.
   NXrouting_PktTimer pkt_timer_; // Timer for sending packets.

   //add by tl to support multiple interfaces
   int nIfaces;
   NsObject *targetlist[MAX_IF];
   PriQueue *ifqueuelist[MAX_IF];
   //end add by tl


   inline nsaddr_t& ra_addr() { return ra_addr_; }
   //inline nxrouting_state& state() { return state_; }
   inline int& accessible_var() { return accessible_var_; }

   void forward_data(Packet*);
   void recv_nxrouting_pkt(Packet*);
   void send_nxrouting_pkt();

   void reset_nxrouting_pkt_timer();
   void mbcast(Packet* p);
   void unicast(Packet* p, int Iface);
   void ubcast(Packet* p, int Iface);
   int getIface(Packet* p);

   public:

   NXrouting(nsaddr_t);
   int command(int, const char*const*);
   void recv(Packet*, Handler*);
   //void mac_failed(Packet*);
};

#endif
